#include "ModuleCLUTSurveySaturation.h"

void ModuleCLUTSurveySaturation::init(QCVModuleHandlerInterface * parent)
{
	this->parent=parent;
	parent->setAutoProcess(false);
	win=new QWidget();
	
	pb_loadFuzzyCLUT=new QPushButton(tr("Load Fuzzy CLUT"),win);
	pb_saveResults=new QPushButton(tr("Save results"),win);
	pb_askMe=new QPushButton(tr("Get flop"),win);
	pb_clear=new QPushButton(tr("Clear results"),win);
	sat_threshold=new QSpinBox(win);
	sat_threshold->setPrefix(tr("sat_threshold="));
	sat_threshold->setSuffix(tr("%"));
	sat_threshold->setRange(5,95);
	sat_threshold->setValue(80);
	
	pbBarFlop=new QProgressBar(win);
	
	sb_nbColorsAsked=new QSpinBox(win);
	sb_nbColorsAsked->setPrefix(tr("nbColorsPerFlop="));
	sb_nbColorsAsked->setRange(1,25);
	sb_nbColorsAsked->setValue(4);
	
	showClassif=new QCheckBox("Display classification",win); 
	
	plotcolors=new PlotColors();
	
	le_question=new QLineEdit(win);
	
	gb_flops_params=new QGroupBox(tr("Flop Parameters"),win);
	
	te_results=new QTextEdit(win);
	
	layout=new QVBoxLayout(win);
	layout->addWidget(pb_loadFuzzyCLUT);
	
	QGridLayout * glayout=new QGridLayout();
	glayout->addWidget(sb_nbColorsAsked,0,0);
	glayout->addWidget(pb_askMe,1,0);
	glayout->addWidget(sat_threshold,0,1);
	glayout->addWidget(pbBarFlop,1,1);
	glayout->addWidget(showClassif,2,0);
	gb_flops_params->setLayout(glayout);
	
	layout->addWidget(gb_flops_params);
	layout->addWidget(le_question);
	layout->addWidget(plotcolors);
	QHBoxLayout * hlayout=new QHBoxLayout();
	hlayout->addWidget(pb_clear);
	hlayout->addWidget(pb_saveResults);
	layout->addLayout(hlayout);
	layout->addWidget(te_results);
	
	connect(pb_clear,SIGNAL(clicked()),this,SLOT(s_clearResults()));
	connect(pb_loadFuzzyCLUT,SIGNAL(clicked()),this,SLOT(s_loadFuzzyCLUT()));
	connect(pb_saveResults,SIGNAL(clicked()),this,SLOT(s_saveResults()));
	connect(pb_askMe,SIGNAL(clicked()),this,SLOT(s_askMe()));
	connect(showClassif,SIGNAL(stateChanged(int)),this,SLOT(s_showClassif(int)));
	
	results=tr("");
	
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::free()
{
	delete win;
}
////////////////////////////////////////////////////////////////////////////////
cv::Mat & ModuleCLUTSurveySaturation::process()
{

}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::setInput(int n,const cv::Mat & m)
{
	
}
////////////////////////////////////////////////////////////////////////////////
QWidget* ModuleCLUTSurveySaturation::widget()
{
	return win;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleCLUTSurveySaturation::getName()
{
	return tr("Survey Type: Saturation Limit");
}
////////////////////////////////////////////////////////////////////////////////
int ModuleCLUTSurveySaturation::nbInputs()
{
	return 1;
}
////////////////////////////////////////////////////////////////////////////////
bool ModuleCLUTSurveySaturation::setParams(QString params)
{
	QStringList list_params=params.split(";");
		
	if(list_params.size()==1)
	{
		return true;
	}
	else
	{
		return false;
	}	
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleCLUTSurveySaturation::getParams()
{
	return tr("no_param");
}

////////////////////////////////////////////////////////////////////////////////
QCVModuleInterface * ModuleCLUTSurveySaturation::clone()
{
	return new ModuleCLUTSurveySaturation;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleCLUTSurveySaturation::help(int id)
{
	if(id==-2)
	{
		return tr("This module provide an interface to make a survey in order to find the limit between chroatic and achromatic colors");
	}
	else if(id==-1)
	{
		return tr("image");
	}
	else if(id==0)
	{
		return tr("image");
	}
	else
	{
		return tr("erreur");
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::s_loadFuzzyCLUT()
{
	QString fn=QFileDialog::getOpenFileName(win,"Charger une Fuzzy CLUT","data","*.txt");
	if(!fn.isEmpty())
	{
		if(loadFuzzyCLUT(fn,fuzzyclut))
		{
			maxFuzzyCLUT_2_CLUT(fuzzyclut,clut);
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::s_saveResults()
{
	QString fn=QFileDialog::getSaveFileName(win,"Charger une Fuzzy CLUT","data","*.txt");
	if(!fn.isEmpty())
	{
		QFile file(fn);
		if (file.open(QIODevice::WriteOnly | QIODevice::Text))
		{
			QTextStream out(&file);
			out << results;
			file.close();
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::s_askMe()
{
	srand(time(0));
	QString r = plotcolors->getResults();
	if(!r.isEmpty())
	{
		results+=r;
	}
	te_results->setText(results);
	
	if(!clut.empty())
	{
		//On efface le jeu de couleur precedent
		plotcolors->clearColors();
		
		//On choisi une categorie de couleur parmi les 11 possibles
		color=rand()%11;
		plotcolors->setColors(color,color);
		le_question->setText(tr("Which of these colors are ")+getC11Name(color)+tr("?"));
		
		pbBarFlop->setRange(0,round(pow(clut.rows,1.0/3.0)));
		int p=(int)256/round(pow(clut.rows,1.0/3.0));
		
		//On construit une listes des couleurs classifie selon la categorie choisie
		QList<QColor> colors;
		for(int r=0;r<256;r+=p)
		{
			for(int g=0;g<256;g+=p)
			{
				for(int b=0;b<256;b+=p)
				{
					if(CLUT(clut,r,g,b)==color)
					{
						colors+=QColor(r,g,b,color);
					}
				}
			}
			pbBarFlop->setValue(r);
		}
		
		//On cherche le min et max de la saturation de ce sous espace de couleur
		uchar L=0,S=0;
		uchar sat_max=0,sat_min=255;
		for(int i=0;i<colors.size();i++)
		{
			getBriSat(colors[i].red(),colors[i].green(),colors[i].blue(),&L,&S);
			if(S>sat_max){sat_max=S;}
			if(S<=sat_min){sat_min=S;}
		}

		//QMessageBox::information(NULL,"",QString::number(sat_max)+tr("-")+QString::number(sat_min));
		
		//Calcule la valeur du seuil de saturation
		uchar sat_threshold1=(uchar) (sat_threshold->value()/100.0*(sat_max-sat_min)+sat_min);
		uchar sat_threshold2=(uchar) ((1-(sat_threshold->value()/100.0))*(sat_max-sat_min)+sat_min);

		//On divise cet espace en deux sous-categorie
		QList<QColor> colors_lowSat;
		QList<QColor> colors_highSat;
		for(int i=0;i<colors.size();i++)
		{
			getBriSat(colors[i].red(),colors[i].green(),colors[i].blue(),&L,&S);
			if(S>sat_threshold1)colors_highSat+=colors[i];
			if(S<=sat_threshold2)colors_lowSat+=colors[i];
		}
		
		//QMessageBox::information(NULL,"",QString::number(colors_lowSat.size())+tr("-")+QString::number(colors_highSat.size()));
		
		for(int i=0;i<sb_nbColorsAsked->value();i++)
		{
			if(i==0)
			{
				plotcolors->addColors(colors_highSat[rand()%colors_highSat.size()]);
			}
			else if(i==(sb_nbColorsAsked->value()-1))
			{
				plotcolors->addColors(colors_highSat[rand()%colors_highSat.size()]);
			}
			else
			{
				plotcolors->addColors(colors_lowSat[rand()%colors_lowSat.size()]);
			}
			
		}
	}
	else
	{
		le_question->setText(tr("Oups! I need a Fuzzy CLUT please..."));
	}
	parent->adjust();
}
void ModuleCLUTSurveySaturation::s_clearResults()
{
	results.clear();
	te_results->clear();
	te_results->setText(results);
}

////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::s_showClassif(int display)
{
	plotcolors->displayClassif(display);
	plotcolors->update();
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveySaturation::getBriSat(uchar r,uchar g,uchar b,uchar * L,uchar * S)
{
	uchar var_Min = std::min( std::min(r, g), b );    //Min. value of RGB
	uchar var_Max = std::max( std::max(r, g), b );    //Max. value of RGB
	uchar del_Max = var_Max - var_Min; 				//Delta RGB value

	*L = ( var_Max + var_Min ) / 2;

	if ( del_Max == 0 )                     //This is a gray, no chroma...
	{		                                //HSL results from 0 to 1
		*S = 0;
	}
	else                                    //Chromatic data...
	{
		if ( *L < 128 ) *S = (255 * del_Max) / ( var_Max + var_Min );
		else           *S = (255 * del_Max) / ( 512 - var_Max - var_Min );
	}
}

////////////////////////////////////////////////////////////////////////////////

Q_EXPORT_PLUGIN2(ModuleCLUTSurveySaturation_plugin,ModuleCLUTSurveySaturation);  
